﻿using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.UI;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Esri.ArcGISRuntime.UI.Controls;
using System.Collections.Generic;
using WRJClient.Utils;

namespace WRJClient.UI.Map
{
    /// <summary>
    /// BaseMap.xaml 的交互逻辑
    /// </summary>
    public partial class BaseMap : UserControl
    {
        private Dictionary<string, GraphicsOverlay> _layers;
        public Dictionary<string, GraphicsOverlay> Layers { get { return _layers; } }

        private string _mapServerIp = Properties.Settings.Default.MapServerIp;
        private int _mapServerPort = Properties.Settings.Default.MapServerPort;
        public string MapServerIp
        {
            get { return _mapServerIp; }
            set { _mapServerIp = value; }
        }
        public int MapServerPort
        {
            get { return _mapServerPort; }
            set { _mapServerPort = value; }
        }

        private string[] Urls = new string[]
        {
            "/arctiler/arcgis/services/ArcGISCache2/MapServer",
            "/arctiler/arcgis/services/ArcGISCache1/MapServer",
            "/arctiler/arcgis/services/OpenStreetDiXingCache/MapServer",
            "/arctiler/arcgis/services/GaoDeJieDaoCache/MapServer",
            "/arctiler/arcgis/services/GaoDeJieDaoCache_gray/MapServer"
        };

        private string GetMapUrl(int index)
        {
            if (index >= Urls.Count())
            {
                index = 0;
            }
            string url = string.Format("http://{0}:{1}{2}", _mapServerIp, _mapServerPort, Urls.ElementAt(index));
            return url;
        }

        public MapView MapView
        {
            get { return mapView; }
        }

        public BaseMap()
        {
            InitializeComponent();
            //initBaseMap();
            InitGraphicsOverlays();
        }

        public void InitBaseMap()
        {
            try
            {
                string MapUrl = GetMapUrl(0);
                var imageryTiledLayer = new ArcGISTiledLayer(new Uri(MapUrl));
                var myBasemap = new Basemap(imageryTiledLayer);
                mapView.Map = new Esri.ArcGISRuntime.Mapping.Map(myBasemap);
                mapView.Map.MaxScale = 342.70509619687994;
                mapView.Map.MinScale = 916463.41326366272;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

        public void ChangeBaseMap(int index)
        {
            try
            {
                string MapUrl = GetMapUrl(index);
                var imageryTiledLayer = new ArcGISTiledLayer(new Uri(MapUrl));
                var myBasemap = new Basemap(imageryTiledLayer);
                var map = new Esri.ArcGISRuntime.Mapping.Map(myBasemap);
                map.InitialViewpoint = new Viewpoint(mapView.VisibleArea.Extent);
                mapView.Map = map;
                mapView.Map.MaxScale = 342.70509619687994;
                mapView.Map.MinScale = 916463.41326366272;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public async void SetViewPoint(Envelope envelope)
        {
            try
            {
                await mapView.SetViewpointGeometryAsync(envelope);
            }
            catch (Exception)
            {
            }
        }

        public async void SetViewPoint(Geometry geometry)
        {
            if (geometry != null && !geometry.IsEmpty && geometry.Extent.Width > 0.00000001 && geometry.Extent.Height > 0.00000001)
            {
                try
                {
                    await mapView.SetViewpointGeometryAsync(geometry, 100);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                }
            }
        }

        public void PanTo(MapPoint point, double? scale = null)
        {
            if (scale != null)
            {
                mapView.SetViewpointCenterAsync(point, (double)scale);
            }
            else
            {
                mapView.SetViewpointCenterAsync(point);
            }
        }

        private void MapView_OnPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            MapPoint mappoint = mapView.ScreenToLocation(e.GetPosition(mapView));
            if (mappoint != null)
            {
                MapPoint map = (MapPoint)GeometryEngine.Project(mappoint, SpatialReferences.Wgs84);

                // Format the display callout string based upon the projected map point (example: "Lat: 100.123, Long: 100.234")
                string mapLocationDescription = string.Format("Lat: {0}\r\nLong:{1}", map.Y, map.X);
                // Create a new callout definition using the formatted string
                CalloutDefinition myCalloutDefinition = new CalloutDefinition("Location:", mapLocationDescription);
                // Display the callout
                if (mapView.IsCalloutVisible)
                {
                    mapView.DismissCallout();
                }
                else
                {
                    mapView.ShowCalloutAt(mappoint, myCalloutDefinition);
                }


                Console.WriteLine(map.ToJson());
            }

            e.Handled = true;
        }

        private void MapView_Loaded(object sender, RoutedEventArgs e)
        {
            InitBaseMap();
        }

        private void InitGraphicsOverlays()
        {
            _layers = new Dictionary<string, GraphicsOverlay>
            {
                { "Layer0", new GraphicsOverlay() },
                { "Layer1", new GraphicsOverlay() },
                { "Layer2", new GraphicsOverlay() },
                { "Layer3", new GraphicsOverlay() },
                { "Layer4", new GraphicsOverlay() }
            };

            foreach (var item in _layers)
            {
                MapView.GraphicsOverlays.Add(item.Value);
            }
        }

        public GraphicsOverlay GetGraphicsOverlay(string layerName)
        {
            if (_layers.TryGetValue(layerName, out GraphicsOverlay graphicsOverlay))
            {
                return graphicsOverlay;
            }
            MessageBox.Show(string.Format("layer {0} not found!", layerName));
            return null;
        }
        public void Clear()
        {
            foreach (var item in _layers.Values)
            {
                item.Graphics.Clear();
            }
        }

        public void Add(string layerName, BaseGraphic graphic)
        {
            if (graphic != null)
            {
                GraphicsOverlay layer = GetGraphicsOverlay(layerName);

                if (layer != null)
                {
                    layer.Graphics.Add(graphic);
                }
            }
        }

        public void Remove(string layerName, BaseGraphic graphic)
        {
            if (graphic != null)
            {
                GraphicsOverlay layer = GetGraphicsOverlay(layerName);

                if (layer != null)
                {
                    layer.Graphics.Remove(graphic);
                }
            }
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            if (menuItem != null)
            {
                if (menuItem.Name.CompareTo("satelliteMap") == 0)
                {
                    ChangeBaseMap(0);
                }
                else if (menuItem.Name.CompareTo("streetMap") == 0)
                {
                    ChangeBaseMap(1);
                }
            }
        }
    }
}
